package cn.zyq.ykb.service.sys.impl;


import cn.zyq.ykb.beans.sys.SysAdmin;
import cn.zyq.ykb.beans.sys.SysJob;
import cn.zyq.ykb.mapper.sys.SysJobMapper;
import cn.zyq.ykb.service.sys.SysJobService;
import cn.zyq.ykb.system.common.BaseService;
import cn.zyq.ykb.system.common.PageParam;
import cn.zyq.ykb.system.ry.quartz.ScheduleConstants;
import cn.zyq.ykb.system.ry.quartz.ScheduleUtils;
import cn.zyq.ykb.system.ry.quartz.TaskException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * 定时任务调度表
 * 2023-05-12 20:14:08
 */

@Slf4j
@Service
public class SysJobServiceImpl extends BaseService implements SysJobService {
    @Autowired
    private SysJobMapper sysJobMapper;

    @Autowired
    private Scheduler scheduler;

    /**
     * 项目启动时，初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理（注：不能手动修改数据库ID和任务组名，否则会导致脏数据）
     */
    @PostConstruct
    public void init() throws SchedulerException, TaskException {
        scheduler.clear();
        List<SysJob> jobList = sysJobMapper.selectAll();
        for (SysJob job : jobList) {
            ScheduleUtils.createScheduleJob(scheduler, job);
        }
    }

    @Override
    public PageInfo<SysJob> list(PageParam pageParam) {
        PageHelper.startPage(pageParam.getPage(), pageParam.getPageSize());
        List<SysJob> dbList = this.sysJobMapper.list(pageParam.getKv());
        return new PageInfo<>(dbList);
    }

    @Override
    public void add(SysJob param, SysAdmin admin) throws SchedulerException, TaskException {
        param.setStatus(ScheduleConstants.Status.PAUSE.getValue());
        this.setCreateBaseData(param, admin);
        int i = this.sysJobMapper.insertSelective(param);
        if (i > 0) {
            ScheduleUtils.createScheduleJob(scheduler, param);
        }
    }

    @Override
    public void update(SysJob param, SysAdmin admin) throws SchedulerException, TaskException {
        Integer id = param.getSysJobID();
        SysJob sysJob = this.sysJobMapper.selectByPrimaryKey(id);
        this.setUpdateBaseData(param, admin);
        int rows = this.sysJobMapper.updateByPrimaryKeySelective(param);
        if (rows > 0) {
            updateSchedulerJob(param, sysJob.getJobGroup());
        }
    }

    /**
     * 更新任务
     *
     * @param job      任务对象
     * @param jobGroup 任务组名
     */
    public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException {
        Integer jobId = job.getSysJobID();
        // 判断是否存在
        JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        ScheduleUtils.createScheduleJob(scheduler, job);
    }


    @Override
    public void del(String serviceID, SysAdmin admin) {
        SysJob dbInfo = this.detail(serviceID);
        Integer id = dbInfo.getSysJobID();
        this.deleteLogic(id, admin, this.sysJobMapper);
    }

    @Override
    public SysJob detail(String serviceID, SysAdmin admin) {
        return this.detail(serviceID);
    }

    @Override
    public SysJob detail(String serviceID) {
        SysJob dbInfo = this.getByServiceID(serviceID, SysJob.class, this.sysJobMapper);
        this.checkLogicExist(dbInfo);
        return dbInfo;
    }

    @Override
    public List<SysJob> selectJobList(SysJob sysJob) {
        return this.sysJobMapper.selectJobList(sysJob);
    }

    @Override
    public SysJob selectJobById(Integer jobId) {
        return sysJobMapper.selectByPrimaryKey(jobId);
    }

    @Override
    public int changeStatus(SysJob job) throws SchedulerException {
        int rows = 0;
        String status = job.getStatus();
        if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) {
            rows = resumeJob(job);
        } else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) {
            rows = pauseJob(job);
        }
        return rows;
    }

    /**
     * 恢复任务
     *
     * @param job 调度信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int resumeJob(SysJob job) throws SchedulerException {
        Integer jobId = job.getSysJobID();
        String jobGroup = job.getJobGroup();
        job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
        int rows = sysJobMapper.updateByPrimaryKeySelective(job);
        if (rows > 0) {
            scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));
        }
        return rows;
    }

    /**
     * 暂停任务
     *
     * @param job 调度信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int pauseJob(SysJob job) throws SchedulerException {
        Integer jobId = job.getSysJobID();
        String jobGroup = job.getJobGroup();
        job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
        int rows = sysJobMapper.updateByPrimaryKeySelective(job);
        if (rows > 0) {
            scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
        }
        return rows;
    }

    /**
     * 立即运行任务
     *
     * @param job 调度信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean run(SysJob job) throws SchedulerException {
        boolean result = false;
        Integer jobId = job.getSysJobID();
        String jobGroup = job.getJobGroup();
        SysJob properties = selectJobById(job.getSysJobID());
        // 参数
        JobDataMap dataMap = new JobDataMap();
        dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
        JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
        if (scheduler.checkExists(jobKey)) {
            result = true;
            scheduler.triggerJob(jobKey, dataMap);
        }
        return result;
    }

    /**
     * 批量删除调度信息
     *
     * @param jobIds 需要删除的任务ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteJobByIds(Integer[] jobIds) throws SchedulerException {
        for (Integer jobId : jobIds) {
            SysJob job = sysJobMapper.selectByPrimaryKey(jobId);
            deleteJob(job);
        }
    }

    /**
     * 删除任务后，所对应的trigger也将被删除
     *
     * @param job 调度信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteJob(SysJob job) throws SchedulerException {
        Integer jobId = job.getSysJobID();
        String jobGroup = job.getJobGroup();
        int rows = sysJobMapper.deleteByPrimaryKey(jobId);
        if (rows > 0) {
            scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
        }
        return rows;
    }
}
